//  这句话用来编程时自动提示，运行时需要注释掉！
//import * as BABYLON from '@babylonjs/core';

var canvas = document.getElementById("renderCanvas");

var startRenderLoop = function (engine, canvas) {
  engine.runRenderLoop(function () {
    if (sceneToRender && sceneToRender.activeCamera) {
      sceneToRender.render();
    }
  });
};

var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
  return new BABYLON.Engine(canvas, true, {
    preserveDrawingBuffer: true,
    stencil: true,
    disableWebGL2Support: false,
  });
};


//  创建场景（相关代码都在此处）
var createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  var scene = new BABYLON.Scene(engine);
  
  //  创建相机
  var camera = new BABYLON.ArcRotateCamera(
    "camera",
    BABYLON.Tools.ToRadians(90),
    BABYLON.Tools.ToRadians(65),
    10,
    BABYLON.Vector3.Zero(),
    scene
  );
  camera.attachControl(canvas, true);
  //  创建灯光
  var light = new BABYLON.HemisphericLight(
    "light",
    new BABYLON.Vector3(1, 1, 0),
    scene
  );
  //  X轴
  const myLines = BABYLON.MeshBuilder.CreateLines("lines", {points: [new BABYLON.Vector3(0, 0, 0),new BABYLON.Vector3(8, 0, 0)]});
  //  Ground
  const ground = buildGround();

  //  创建房子
  const detached_house = buildHouse(1);
  detached_house.rotation.y = -Math.PI/16;
  detached_house.position.x = -6.8;
  detached_house.position.z = 2.5;

  const semi_house = buildHouse(2);
  semi_house.rotation.y = -Math.PI/16;
  semi_house.position.x = -4.5;
  semi_house.position.z = 3;

  //  数组中每一个数为[house类型,rotation, x, z]
  const places = [];
  places.push([1, -Math.PI / 16, -6.8, 2.5 ]);
  places.push([2, -Math.PI / 16, -4.5, 3 ]);
  places.push([2, -Math.PI / 16, -1.5, 4 ]);
  places.push([2, -Math.PI / 3, 1.5, 6 ]);
  places.push([2, 15 * Math.PI / 16, -6.4, -1.5 ]);
  places.push([1, 15 * Math.PI / 16, -4.1, -1 ]);
  places.push([2, 15 * Math.PI / 16, -2.1, -0.5 ]);
  places.push([1, 5 * Math.PI / 4, 0, -1 ]);
  places.push([1, Math.PI + Math.PI / 2.5, 0.5, -3 ]);
  places.push([2, Math.PI + Math.PI / 2.1, 0.75, -5 ]);
  places.push([1, Math.PI + Math.PI / 2.25, 0.75, -7 ]);
  places.push([2, Math.PI / 1.9, 4.75, -1 ]);
  places.push([1, Math.PI / 1.95, 4.5, -3 ]);
  places.push([2, Math.PI / 1.9, 4.75, -5 ]);
  places.push([1, Math.PI / 1.9, 4.75, -7 ]);
  places.push([2, -Math.PI / 3, 5.25, 2 ]);
  places.push([1, -Math.PI / 3, 6, 4 ]);


  const houses = [];
  for(let i=0; i<places.length; i++){
    if(places[i][0] === 1){
      houses[i] = detached_house.createInstance("house" + i);
    }
    else{
      houses[i] = semi_house.createInstance("house" + i);
    }
    houses[i].rotation.y = places[i][1];
    houses[i].position.x = places[i][2];
    houses[i].position.z = places[i][3];
  }

  return scene;
};

//  创建地面
const buildGround = ()=>{
  const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 16, height: 16 }, scene);
  const groundMat = new BABYLON.StandardMaterial("groundMat", scene);
  groundMat.diffuseColor = new BABYLON.Color3(0, 1, 0);
  ground.material = groundMat;
}

//  创建房子（每个mesh使用各自的材质）
const buildHouse = (width)=>{
  const box = buildBox(width);
  const roof = buildRoof(width);

  return BABYLON.Mesh.MergeMeshes([box, roof], true, false, null, false, true);
}

//  创建房顶
const buildRoof = (width)=>{
  //  创建房顶(通过圆柱体创建)
  const roof = BABYLON.MeshBuilder.CreateCylinder("roof", { diameter: 1.3, height: 1.2, tessellation:3});
  roof.scaling.x = 0.75;
  roof.scaling.y = width;
  roof.rotation.z = Math.PI/2.0;
  roof.position.y = 1.22;

  //  创建材质
  const roofMat = new BABYLON.StandardMaterial("roofMat");
  roofMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg");
  roof.material = roofMat;

  return roof;
}

//  创建盒子
const buildBox = (width)=>{

  //  texture
  const boxMat = new BABYLON.StandardMaterial("boxMat");
  if(width === 2){
    boxMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/semihouse.png");
  }
  else{
    boxMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/cubehouse.png");
  }

  const faceUV = [];
  if(width === 2){
    faceUV[0] = new BABYLON.Vector4(0.6, 0.0, 1.0, 1.0);  //rear face
    faceUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.4, 1.0);  //front face
    faceUV[2] = new BABYLON.Vector4(0.4, 0.0, 0.6, 1.0);  //right side
    faceUV[3] = new BABYLON.Vector4(0.4, 0.0, 0.6, 1.0);  //left side
  }
  else{
    faceUV[0] = new BABYLON.Vector4(0.5, 0.0, 0.75, 1.0);  //rear face
    faceUV[1] = new BABYLON.Vector4(0.75, 0.0, 1.0, 1.0);  //front face
    faceUV[2] = new BABYLON.Vector4(0.0, 0.0, 0.25, 1.0);  //right side
    faceUV[3] = new BABYLON.Vector4(0.25, 0.0, 0.5, 1.0);  //left side
  }

  const box = BABYLON.MeshBuilder.CreateBox("box", { width: width, faceUV: faceUV, Wrap: true });
  box.material = boxMat;
  box.position.y = 0.5;

  return box;
}

//================================================

window.initFunction = async function () {
  var asyncEngineCreation = async function () {
    try {
      return createDefaultEngine();
    } catch (e) {
      console.log(
        "the available createEngine function failed. Creating the default engine instead"
      );
      return createDefaultEngine();
    }
  };

  window.engine = await asyncEngineCreation();
  if (!engine) throw "engine should not be null.";
  startRenderLoop(engine, canvas);
  window.scene = createScene();
};
initFunction().then(() => {
  sceneToRender = scene;
});

// Resize
window.addEventListener("resize", function () {
  engine.resize();
});